home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 98 / Skunkware 98.iso / osr5 / sco / scripts / admin / callout < prev    next >
Encoding:
AWK Script  |  1997-08-26  |  13.1 KB  |  422 lines

  1. #!/usr/local/bin/gawk -f
  2. #!/usr/bin/awk -f
  3. # @(#) callout.gawk 3.0 93/05/02
  4. # callout: turn uucico or cu callout on and off
  5. # 91/03/14 john h. dubois iii
  6. # 91/04/02 changed method of disabling callout from moving Devices file
  7. #          to making it unreadable
  8. # 91/06/11 made uurun report callout status if no args given
  9. # 92/02/25 changed name to "callout"; controls both cu and uucico callout
  10. # 92/03/13 Changed to only modify user and group perms on Devices files.
  11. # 93/05/02 Use Sysfiles; rewrote as awk script; added t option
  12.  
  13. BEGIN {
  14.     name = "callout"
  15.     if ((ARGC = ProcArgs(ARGC,ARGV,"htx:",Options,1)) < 0) {
  16.     printf "%s: %s\nUse -h for help.\n",name,OptErr
  17.     exit 1
  18.     }
  19.     if ("h" in Options) {
  20.     printf \
  21. "Syntax: %s [-ht] [-x<n>] [service-name  [service-name ...]] [on|off]\n"\
  22. "%s without arguments reports the status of the default services.\n"\
  23. "The default services are cu, ct, and uucico.\n"\
  24. "%s on      enables callout on devices by the default services.\n"\
  25. "%s off    disables callout on devices by the default services.\n"\
  26. "If service names (typically one of the default services) are given,\n"\
  27. "actions are restricted to the named services as much as possible.\n"\
  28. "Service disabling is done by changing the permissions on devices files,\n"\
  29. "so actions on a service will affect services it shares devices files with.\n"\
  30. "Device files that do not exist or are not writable by uucp are ignored.\n"\
  31. "-h prints this help.\n"\
  32. "-t prints the actions that would be taken but makes no changes.\n"\
  33. "-x<n> turns on debugging.  Higher values of n give more information.\n",
  34. name,name,name,name
  35.     exit 1
  36.     }
  37.     if ("x" in Options)
  38.     debug = Options["x"]
  39.     for (i = 1; i < ARGC; i++) {
  40.     arg = ARGV[i]
  41.     if (arg == "on" || arg == "off")
  42.         Change = arg
  43.     else
  44.         Services = Services ":" arg
  45.     }
  46.     if (Services == "")
  47.     Services = "cu:ct:uucico"
  48.     else
  49.     Services = substr(Services,2)
  50.     ReadSysfiles("/usr/lib/uucp/Sysfiles",Sysfiles,"/usr/lib/uucp",Services,
  51.     AllServices)
  52.     MakeSet(ServArr,Services,":")
  53.     for (Service in ServArr)
  54.     MakeSet(Devices,Sysfiles[Service,"devices"],":")
  55.     devstat(Devices)
  56.     if (debug > 1)
  57.     for (Device in Devices)
  58.         if (Devices[Device])
  59.         printf "%s is readable.\n",Device
  60.         else
  61.         printf "%s is not readable.\n",Device
  62.     MakeSet(ServEnab,Services,":")
  63.     ServStat(ServEnab,Sysfiles,Devices)
  64.     if (Change == "")
  65.     for (Service in ServArr)
  66.         printf "%6s %s\n",Service,ServEnab[Service]
  67.     else 
  68.     ChDev(Change,ServArr,ServEnab,Devices,Sysfiles,AllServices)
  69. }
  70.  
  71. # Change is "on" or "off" to make devices files readable or not readable.
  72. # ServArr is the list of services to change device files for.
  73. # ServEnab tells what the current status for the service is.
  74. # DevStat gives the devices files to change.
  75. function ChDev(Change,ServArr,ServEnab,DevStat,Sysfiles,AllServices,
  76. Service,Dev,Readable,DevList,Ch,Cmd,Inverse,Note) {
  77.     Inverse["on"] = "off"
  78.     Inverse["off"] = "on"
  79.     for (Service in ServArr) {
  80.     if (Service SUBSEP Change in ServEnab && \
  81.     !(Service SUBSEP Inverse[Change] in ServEnab)) {
  82.         printf "Already %3s %s.\n",Change ":",Service
  83.         continue
  84.     }
  85.     }
  86.     Readable = Change == "on"
  87.     for (Dev in DevStat) {
  88.     if (DevStat[Dev] == Readable) {
  89.         if (debug > 1)
  90.         printf "%s: no change.\n",Dev
  91.     }
  92.     else {
  93.         DevList = DevList " " Dev
  94.         if (debug > 1)
  95.         printf "%s: changed.\n",Dev
  96.         for (Service in AllServices) {
  97.         if (!(Service in ServArr) && \
  98.         Sysfiles[Service,"devices"] ~ "(^|:)" Dev "(:|$)") {
  99.             if (!Note) {
  100.             printf "Note: %s also used by services:",Dev
  101.             Note = 1
  102.             }
  103.             printf " " Service
  104.         }
  105.         }
  106.         if (Note) {
  107.         print ""
  108.         Note = 0
  109.         }
  110.     }
  111.     }
  112.     if (debug > 1)
  113.     printf "changed: %s\n",DevList
  114.     if (Readable)
  115.     Ch = "+"
  116.     else
  117.     Ch = "-"
  118.     Cmd = "chmod ug" Ch "r" DevList
  119.     if ("t" in Options)
  120.     print "Would do: " Cmd
  121.     else
  122.     system(Cmd)
  123. }
  124.  
  125. # For each service that is an index of Services,
  126. # sets Services[service,"on"] if it has readable device files and
  127. # sets Services[service,"off"] if it has unreadable device files.
  128. # Also sets Services[service] to "enabled", "disabled", or "partially enabled".
  129. # Sysfiles gives the devices files used by services.
  130. # DevStat gives the status of device files.
  131. # Devices listed in Sysfiles but not in DevStat are ignored.
  132. function ServStat(Services,Sysfiles,DevStat,  Dev,Service,n,i) {
  133.     for (Service in Services) {
  134.     n = split(Sysfiles[Service,"devices"],Dev,":")
  135.     for (i = 1; i <= n; i++)
  136.         if (Dev[i] in DevStat)
  137.         if (DevStat[Dev[i]])
  138.             Services[Service,"on"]
  139.         else
  140.             Services[Service,"off"]
  141.     if ((Service SUBSEP "on") in Services)
  142.         Services[Service] = "enabled"
  143.     if ((Service SUBSEP "off") in Services)
  144.         if (Services[Service] == "enabled")
  145.         Services[Service] = "partially enabled"
  146.         else
  147.         Services[Service] = "disabled"
  148.     }
  149. }
  150.  
  151. function Union(A,B,Both,  Elem) {
  152.     for (Elem in A)
  153.     Both[Elem]
  154.     for (Elem in B)
  155.     Both[Elem]
  156. }
  157.  
  158. # Returns 1 if Set is empty, 0 if not.
  159. function IsEmpty(Set,  i) {
  160.     for (i in Set)
  161.     return 0
  162.     return 1
  163. }
  164.  
  165. # Usage: devstat(Files)
  166. # Files is an array with indices giving the names of files to stat.
  167. # For each file in the array, its value is set to 1 if the file is
  168. # readable by uucp, 0 if it is not.
  169. # If the file is not writable by uucp, it is removed from Files.
  170. # Nonzero is returned if an error occurs.
  171. function devstat(Files,  Cmd,stats,Device,DevList,ret) {
  172.     for (Device in Files)
  173.     DevList = DevList " " Device
  174.     split("",Files)
  175.     if (DevList == "")
  176.     return 0
  177.     Cmd = "su uucp -c 'for device_file in " DevList \
  178.     "; do [ ! -w $device_file ] && continue; [ -r $device_file ];" \
  179.     "echo $device_file $?; done; exit 0'"
  180.     while ((ret = (Cmd | getline)) == 1)
  181.     Files[$1] = $2 == 0
  182.     close(Cmd)
  183.     return ret
  184. }
  185.  
  186. # ReadSysfiles: read & parse Sysfiles.
  187. # SysFileName should be the name of the sysfiles file,
  188. # usually /usr/lib/uucp/Sysfiles.
  189. # It is read and the files assigned to services are put in Sysfiles
  190. # indexed by service name and file type.
  191. # The value consists of filenames separated by colons in the same order
  192. # that they are given in the sysfiles file.
  193. # If DefDir is given, it is prepended to any non-absolute path names.
  194. # Usual service names are cu, ct, and uucico.
  195. # Usual file types are systems, devices, and dialers.
  196. # Services is a colon-separated list of services.  If it is given, 
  197. # the default values for systems, devices, and dialers are put in
  198. # Sysfiles for the service if they are not specified in the sysfiles file.
  199. # An index is createdin AllServices for every service found.
  200. # Example: to get the devices files used by cu, use Sysfiles["cu","devices"]
  201. # If the given sysfile does not exist or cannot be read,
  202. # the array is left empty and -1 is returned.
  203. # Otherwise, 0 is returned.
  204. # Example call:
  205. # ReadSysfiles("/usr/lib/uucp/Sysfiles",Sysfiles,"/usr/lib/uucp",
  206. # "cu:ct:uucico",AllServices)
  207. function ReadSysfiles(SysfileName,Sysfiles,DefDir,Services,AllServices,
  208. NumServ,ServNames,FileTypes,Service,FileType,
  209. SysfilesLines,NumLines,Assignments,Assignment,i,j,Ind,Var,Val,Files,NumFiles) {
  210.     split("",SysfilesLines)
  211.     if ((NumLines = ReadRecFile(SysfileName,SysfilesLines)) == -1)
  212.     return -1
  213.     if (DefDir ~ "[^/]$")
  214.     DefDir = DefDir "/"
  215.     for (i = 1; i <= NumLines; i++) {
  216.     if (debug > 1)
  217.         print "sysfiles line: " SysfilesLines[i] | "cat 1>&2"
  218.         split(SysfilesLines[i],Assignments,"[ \t]+")
  219.     split("",VarVal)
  220.     for (j in Assignments) {
  221.         if (debug > 1)
  222.         print "Assignment: " Assignments[j] | "cat 1>&2"
  223.         # More than one assignment for the same file type may be given
  224.         # on a line
  225.         Var = Val = Assignments[j]
  226.         sub("=.*$","",Var)
  227.         sub("^[^=]*=","",Val)
  228.         if (Var in VarVal)
  229.         VarVal[Var] = VarVal[Var] ":" Val
  230.         else
  231.         VarVal[Var] = Val
  232.     }
  233.     if (!("service" in VarVal)) {
  234.         if (debug)
  235.         print "No service given on Sysfiles line: " Sysfiles[i] | \
  236.         "cat 1>&2"
  237.         continue
  238.     }
  239.     # More than one service name may be given
  240.     split("",ServNames)
  241.     MakeSet(ServNames,VarVal["service"],":")
  242.     for (Var in VarVal) {
  243.         NumFiles = split(VarVal[Var],Files,":")
  244.         for (j = 1; j <= NumFiles; j++) {
  245.         Val = Files[j]
  246.         if (Var == "service")
  247.             AllServices[Val]
  248.         else {
  249.             if (Val !~ "^/")
  250.             Val = DefDir Val
  251.             for (Service in ServNames) {
  252.             Ind = Service SUBSEP Var
  253.             if (Ind in Sysfiles)
  254.                 Sysfiles[Ind] = Sysfiles[Ind] ":" Val
  255.             else
  256.                 Sysfiles[Ind] = Val
  257.             if (debug > 1)
  258.                 printf "Sysfiles[%s,%s] = %s\n",
  259.                 Service,Var,Sysfiles[Ind] | "cat 1>&2"
  260.             }
  261.         }
  262.         }
  263.     }
  264.     }
  265.     if (Services != "") {
  266.     split("",ServNames)
  267.     MakeSet(ServNames,Services,":")
  268.     MakeSet(FileTypes,"systems:devices:dialers",":")
  269.     for (Service in ServNames)
  270.         for (FileType in FileTypes) {
  271.         Ind = Service SUBSEP FileType
  272.         if (!(Ind in Sysfiles)) {
  273.             Sysfiles[Ind] = DefDir toupper(substr(FileType,1,1)) \
  274.             substr(FileType,2)
  275.             if (debug > 1)
  276.             printf "Adding default: Sysfiles[%s,%s] = %s\n",
  277.             Service,FileType,Sysfiles[Ind] | "cat 1>&2"
  278.         }
  279.         }
  280.     }
  281. }
  282.  
  283. # MakeSet: make a set from a list.
  284. # An index with the name of each element of the list
  285. # is created in the given array.
  286. # Input variables: 
  287. # Elements is a string containing the list of elements.
  288. # Sep is the character that separates the elements of the list.
  289. # Output variables:
  290. # Set is the array.
  291. function MakeSet(Set,Elements,Sep,  Num,Names) {
  292.     Num = split(Elements,Names,Sep)
  293.     for (; Num; Num--)
  294.         Set[Names[Num]]
  295. }
  296.  
  297. # ProcArgs.awk   john h. dubois iii   92/02/29
  298. # optlist is a string which contains all of the possible command line options.
  299. # If a character is followed by a colon, 
  300. # it indicates that that option takes an argument.
  301. # Strings in argv[] which begin with "-" or "+" are taken to be
  302. # strings of options, except that a string which consists solely of "-" or
  303. # "+" is not taken to be an option string (it is not acted on).
  304. # If an optoin takes an argument, the argument may either immedately
  305. # follow it or be given separately.
  306.  
  307. # If an option that does not take an argument is given,
  308. # an index with its name is created in options and its value is set to "1".
  309. # If an option that does take an argument is given,
  310. # an index with its name is created in options and its value
  311. # is set to the value of the argument given for it.
  312. # Options and their arguments are deleted from argv.
  313. # Note that this means that there may be gaps 
  314. # left in the indices of argv[].
  315. # If compress is nonzero, argv[] is packed by moving its elements so that
  316. # they have contiguous integer indices starting with 0.
  317. # argv[0] is not examined.
  318. # An argument of "--" or "++" stops the scanning of argv[].
  319. # The number of arguments left in argc is returned.
  320. # If an error occurs,
  321. # the string OptErr is set to an error message and -1 is returned.
  322. function ProcArgs(argc,argv,optlist,options,compress,
  323. ArgNum,ArgsLeft,Arg,ArgLen,ArgInd,Option,Pos) {
  324. # ArgNum is the index of the argument being processed.
  325. # ArgsLeft is the number of arguments left in argv.
  326. # Arg is the argument being processed.
  327. # ArgLen is the length of the argument being processed.
  328. # ArgInd is the position of the character in Arg being processed.
  329. # Option is the character in Arg being processed.
  330. # Pos is the position in optlist of the option being processed.
  331.     ArgsLeft = argc
  332.     for (ArgNum = 1; ArgNum < argc; ArgNum++) {
  333.     Arg = argv[ArgNum]
  334.     if (Arg ~ "^[-+]") {
  335.         if ((Arg == "-") || (Arg == "+"))
  336.         continue
  337.         delete argv[ArgNum]
  338.         ArgsLeft--
  339.         if ((Arg == "--") || (Arg == "++"))
  340.         break
  341.         ArgLen = length(Arg)
  342.         for (ArgInd = 2; ArgInd <= ArgLen; ArgInd++) {
  343.         Option = substr(Arg,ArgInd,1)
  344.         Pos = index(optlist,Option)
  345.         if (!Pos) {
  346.             OptErr = "Invalid option: -" Option
  347.             return -1
  348.         }
  349.         if (substr(optlist,Pos + 1,1) == ":") {
  350.             if (ArgInd < ArgLen) {
  351.             options[Option] = substr(Arg,ArgInd + 1)
  352.             ArgInd = ArgLen
  353.             }
  354.             else {
  355.             if (ArgNum < (argc - 1)) {
  356.                 options[Option] = argv[++ArgNum]
  357.                 delete argv[ArgNum]
  358.                 ArgsLeft--
  359.             }
  360.             else {
  361.                 OptErr = "Option -" Option " requires an argument."
  362.                 return -1
  363.             }
  364.             }
  365.         }
  366.         else
  367.             options[Option] = 1
  368.         }
  369.     }
  370.     }
  371.     if (compress != 0)
  372.     PackArr(argv,ArgsLeft)
  373.     return ArgsLeft
  374. }
  375.  
  376. # Packs Arr to indices starting with 0
  377. # Num should be the number of elements in Arr
  378. function PackArr(Arr,Num,  NewInd,OldInd) {
  379.     NewInd = OldInd = 0
  380.     for (; Num; Num--) {
  381.     while (!(OldInd in Arr))
  382.         OldInd++
  383.     if (NewInd != OldInd) {
  384.         Arr[NewInd] = Arr[OldInd]
  385.         delete Arr[OldInd]
  386.     }
  387.     OldInd++
  388.     NewInd++
  389.     }
  390. }
  391.  
  392. # ReadRecFile: read file File in array Arr[].
  393. # One logical line is stored in each element of Arr[].
  394. # The elements of Arr[] have numeric indices starting with 1.
  395. # A logical line is extended onto another line if it ends with a backslash.
  396. # The backslash may be followed by whitespace.
  397. # The backslash and any trailing whitespace are converted into a single
  398. # space when the physical lines are joined into a logical line.
  399. # If an error occurs, -1 is returned.
  400. # Otherwise, the number of logical lines read is returned.
  401. function ReadRecFile(File,Arr,  result,i,line)
  402. {
  403.     i = 1
  404.     while ((result = (getline line < File)) == 1) {
  405.     if (!(i in Arr) || (Arr[i] ~ /\\[ \t]*$/)) {
  406.         sub(/\\[ \t]*$/," ",Arr[i])
  407.         Arr[i] = Arr[i] line
  408.     }
  409.     else
  410.         Arr[++i] = line
  411.     }
  412.     close(File)
  413.     if (result)
  414.     return -1
  415.     else {
  416.     if (!(i in Arr) && i > 0)
  417.         i--
  418.     return i
  419.     }
  420. }
  421.  
  422.